package com.ltxtiyu.video.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.ltxtiyu.video.bean.VideoInfoBean;
import com.ltxtiyu.video.cacheDao.ConfigCacheDao;
import com.ltxtiyu.video.cacheDao.MomentCacheDao;
import com.ltxtiyu.video.cacheDao.UserCacheDao;
import com.ltxtiyu.video.cacheDao.VideoCacheDao;
import com.ltxtiyu.video.common.CodeTypeConstant;
import com.ltxtiyu.video.common.ConfigConstant;
import com.ltxtiyu.video.common.JsonTool;
import com.ltxtiyu.video.common.RetEnum;
import com.ltxtiyu.video.dao.ltx.*;
import com.ltxtiyu.video.entity.*;
import com.ltxtiyu.video.service.app.TopicService;
import com.ltxtiyu.video.tool.AliTool;
import com.ltxtiyu.video.tool.ObjectTool;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.*;

/**
 * 话题相关业务
 */
@Service
public class TopicServiceImpl implements TopicService {
    public static final Logger LOGGER = LoggerFactory.getLogger(TopicServiceImpl.class);

    @Autowired
    StringRedisTemplate stringRedisTemplate;    // redis
    @Autowired
    AmqpTemplate amqpTemplate;  // rabbitMq
    @Autowired
    TransportClient transportClient;    // elasticSearch

    @Autowired
    TopicDao topicDao;
    @Autowired
    ConfigCacheDao configCacheDao;
    @Autowired
    MomentCountDao momentCountDao;
    @Autowired
    VideoCacheDao videoCacheDao;
    @Autowired
    MomentLikeDao momentLikeDao;
    @Autowired
    MomentDao momentDao;
    @Autowired
    AreaDao areaDao;
    @Autowired
    UserCacheDao userCacheDao;
    @Autowired
    MomentCacheDao momentCacheDao;
    @Autowired
    UserFollowDao userFollowDao;
    @Autowired
    HotWordDao hotWordDao;


    /**
     * 话题首页详情
     * @param params
     * @return
     */
    @Override
    public String topicIndex(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer topicId = ObjectTool.numberOrNull(params.get("topicId"));
        Integer viewType = ObjectTool.numberOrNull(params.get("viewType"));
        if(topicId == null || viewType == null ||
                (!viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_132) && !viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_133))){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求参数错误
        }
        Topic topic = topicDao.selectByPrimaryKey(topicId);
        if(topic == null){  // 该话题不存在
            return JsonTool.genJson(RetEnum.TOPIC_NOT_EXIST);
        }

        // 获取redis刷新数据到数据库的时间配置
//        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        Integer refreshWriteTime = 300000;
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);

        String publisherPortraitUrl = "";
        User publisher = userCacheDao.selectByPrimaryKey(topic.getPublisher());
        if(StringUtils.isNotBlank(publisher.getHeadPortraitId())){  // 是发布者头像
            publisherPortraitUrl = aliTool.getAccessURL(publisher.getHeadPortraitId());
        }
        String publisherNickName = publisher.getNickName();
        String headPortraitUrl = "";
        Integer viewCount = 0;
        Integer joinCount = 0;
        Map<String, Object> map = new HashMap<>();
        map.put("topicId",topicId);
        map.put("remindType", CodeTypeConstant.MOMENT_REMIND_TYPE_100);
        map.put("permissionType", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);

        if(start.intValue() == 0){
            if(StringUtils.isNotBlank(topic.getHeadPortraitId())){
                headPortraitUrl = aliTool.getAccessURL(topic.getHeadPortraitId());
            }
            // 查询参与该话题的视频的总播放量 播放量从数据库直接获取
            viewCount = topicDao.selectSumViewCount(map);
            // 查询参与该话题的总人数
            joinCount = topicDao.selectSumJoinCount(map);
        }

        List<Map<String,Object>> momentList = new ArrayList<>();
        List<Moment> moments = new ArrayList<>();
        map.put("start",start);
        map.put("rows",rows);
        if(viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_132)){   // 最新
            moments = momentDao.selectMomentListForTopicHot(map);
        }else if(viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_133)){   // 热门
            moments = momentDao.selectMomentListForTopicNew(map);
        }

        for(Moment moment:moments){
            // 获取视频信息
            Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);
            String nickName = "";
            String provinceName = "";
            String cityName = "";
            String tempHeadPortraitUrl = "";
            Integer isFollow = 0;
            if(userId > 0){     // 用户有登陆, 查询关注关系
                if(userId.equals(moment.getPermissionType())){  // 是自己发布的
                    isFollow = -1;  // 自己发布的,没有+ √
                }else {
                    // 查询是否关注
                    Map<String, Object> tempMap = new HashMap<>();
                    tempMap.put("userId",moment.getPublisher());
                    tempMap.put("followerId",userId);
                    List<UserFollow> userFollows = userFollowDao.selectHasFollow(tempMap);
                    if(userFollows.size() > 0){ // 有关注关系
                        isFollow = 1;
                    }
                }
            }
            if(moment != null && moment.getPublisher() != null){
                User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
                if(user.getResidenceProvince() != null){    // 获取省市名称
                    provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
                }
                if(user.getResidenceCity() != null){
                    cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
                }
                if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                    tempHeadPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                }
                nickName = user.getNickName();
            }
            /* 发布人信息 */
            resultMoment.put("publisher",moment.getPublisher());
            resultMoment.put("nickName",nickName);
            resultMoment.put("provinceName",provinceName);
            resultMoment.put("cityName",cityName);
            resultMoment.put("headPortraitUrl",tempHeadPortraitUrl);
            resultMoment.put("isFollow",isFollow);
            momentList.add(resultMoment);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("topicId",topicId);
        result.put("name",topic.getName());
        result.put("headPortraitUrl",headPortraitUrl);
        result.put("description",topic.getDescription());
        result.put("viewCount",viewCount);
        result.put("joinCount",joinCount);
        result.put("publisherPortraitUrl",publisherPortraitUrl);
        result.put("publisherNickName",publisherNickName);
        result.put("momentList",momentList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 搜索内容es
     * @param params
     * @return
     */
    @Override
    public String search(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer searchType = ObjectTool.numberOrNull(params.get("searchType"));
        String content = ObjectTool.stringOrNull(params.get("content"));
        if(content == null || searchType == null){        // 搜索内容为空
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        try{
            // 将搜索记录保存到索引库, 不保存数据库
            Map<String, Object> resouce = new HashMap<>();
            resouce.put("create_time",new Date());
            resouce.put("user_id",userId);
            String userNickName = "";
            if(userId.intValue() > 0){
                User user = userCacheDao.selectByPrimaryKey(userId);
                if(user != null && StringUtils.isNotBlank(user.getNickName())){
                    userNickName = user.getNickName();
                }
            }
            resouce.put("nick_name",userNickName);
            resouce.put("word_name",content);
            transportClient.prepareIndex().setIndex(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_SEARCH_LOG).setType(ConfigConstant.ELASTIC_SEARCH_TYPE_NAME).setSource(resouce).get();
        }catch (Exception e){
            LOGGER.error(">>>>>>>>>>>搜索-保存索引库失败, word_name:{}, 错误信息:{}",content,e);
        }

        List<Map<String,Object>> momentList = new ArrayList<>();
        List<Map<String,Object>> userList = new ArrayList<>();
        List<Map<String,Object>> topicList = new ArrayList<>();

        // 获取redis刷新数据到数据库的时间配置
        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
        // 设置高亮标签
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<ltx>");
        highlightBuilder.postTags("</ltx>");
        if(searchType.equals(CodeTypeConstant.SEARCH_SEARCH_TYPE_140)){     // 搜索:综合
            List<Moment> moments = new ArrayList<>();
            try{
                // 查询视频
                /**
                 *  ES用content_text和content_text.standard查询
                 *  高亮统一用content_text.standard显示, 因为content_text能查询出的content_text.standard也一定能查询出
                 *  设置content_text权重*5
                 *  只查公开
                 */
                MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(content,ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT,ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD).field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT,5f);
                MatchQueryBuilder permissionQuery = QueryBuilders.matchQuery("permission_type", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);// 只查公开的
                BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(queryBuilder).must(permissionQuery);
                highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD);
                SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_MOMENT).setQuery(boolQuery)
                        .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                        .execute().actionGet();
                SearchHits hits = response.getHits();
                for(SearchHit hit : hits){
                    Integer id = (Integer) hit.getSourceAsMap().get("id");   // momentId
                    Moment moment = momentCacheDao.selectByPrimaryKey(id);
                    if(moment != null){
                        // 将搜索的内容替换成高亮搜索结果
                        String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD).fragments()[0].toString();
                        moment.setContentText(highLightContent);
                        moments.add(moment);
                    }
                }
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
            }
            // 获取动态结果信息
            for(Moment moment:moments){
                Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);
                String nickName = "";
                String provinceName = "";
                String cityName = "";
                String tempHeadPortraitUrl = "";
                Integer isFollow = 0;
                if(userId > 0){     // 用户有登陆, 查询关注关系
                    if(userId.equals(moment.getPermissionType())){  // 是自己发布的
                        isFollow = -1;  // 自己发布的,没有+ √
                    }else {
                        // 查询是否关注
                        Map<String, Object> tempMap = new HashMap<>();
                        tempMap.put("userId",moment.getPublisher());
                        tempMap.put("followerId",userId);
                        List<UserFollow> userFollows = userFollowDao.selectHasFollow(tempMap);
                        if(userFollows.size() > 0){ // 有关注关系
                            isFollow = 1;
                        }
                    }
                }
                if(moment != null && moment.getPublisher() != null){
                    User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
                    if(user.getResidenceProvince() != null){    // 获取省市名称
                        provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
                    }
                    if(user.getResidenceCity() != null){
                        cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
                    }
                    if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                        tempHeadPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                    }
                    nickName = user.getNickName();
                }
            /* 发布人信息 */
                resultMoment.put("publisher",moment.getPublisher());
                resultMoment.put("nickName",nickName);
                resultMoment.put("provinceName",provinceName);
                resultMoment.put("cityName",cityName);
                resultMoment.put("headPortraitUrl",tempHeadPortraitUrl);
                resultMoment.put("isFollow",isFollow);
                momentList.add(resultMoment);
            }

            /**
             * 综合页面, 只有第一页才发挥 用户list和话题list
             * 只搜两条数据
             */
            if(start < 10){
                rows = 2;
                // 搜索用户
                try{
                    MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER, content);
                    highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER);
                    SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_USER).setQuery(queryBuilder)
                            .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                            .execute().actionGet();
                    SearchHits hits = response.getHits();
                    for(SearchHit hit : hits){
                        Integer id = (Integer) hit.getSourceAsMap().get("id");   // 用户id
                        Map<String, Object> resultUser = new HashMap<>();
                        User user = userCacheDao.selectByPrimaryKey(id);
                        if(user != null){
                            // 设置高亮显示
                            String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER).fragments()[0].toString();
                            user.setNickName(highLightContent);
                            String headPortraitUrl = "";
                            if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像
                                headPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                            }
                            Integer followCount = userFollowDao.selectFollowerCount(user.getId());    // 粉丝数
                            Integer isFollow = 0;   // 这个默认关注
                            if(userId > 0){     // 用户有登陆, 查询关注关系
                                // 查询是否关注
                                Map<String, Object> map = new HashMap<>();
                                map.put("userId",user.getId());
                                map.put("followerId",userId);
                                List<UserFollow> userFollows = userFollowDao.selectHasFollow(map);
                                if(userFollows.size() > 0){ // 有关注关系
                                    isFollow = 1;
                                }
                            }
                            resultUser.put("id",id);
                            resultUser.put("headPortraitUrl",headPortraitUrl);
                            resultUser.put("nickName",user.getNickName());
                            resultUser.put("followCount",followCount);
                            resultUser.put("isFollow",isFollow);
                            userList.add(resultUser);
                        }
                    }
                }catch (Exception e){
                    LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
                }

                // 查询话题
                try{
                    MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC, content);
                    highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC);
                    SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_TOPIC).setQuery(queryBuilder)
                            .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                            .execute().actionGet();
                    SearchHits hits = response.getHits();
                    for(SearchHit hit : hits) {
                        Integer id = (Integer) hit.getSourceAsMap().get("id");   // 用户id
                        Map<String, Object> resultTopic = new HashMap<>();
                        Topic topic = topicDao.selectByPrimaryKey(id);
                        if(topic != null){
                            // 设置高亮显示
                            String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC).fragments()[0].toString();
                            topic.setName(highLightContent);

                            String headPortraitUrl = "";
                            if(StringUtils.isNotBlank(topic.getHeadPortraitId())){   // 获取头像
                                headPortraitUrl = aliTool.getAccessURL(topic.getHeadPortraitId());
                            }
                            // 查询话题下的视频总数
                            Map<String, Object> map = new HashMap<>();
                            map.put("topicId",id);
                            map.put("remindType", CodeTypeConstant.MOMENT_REMIND_TYPE_100);
                            map.put("permissionType", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);
                            Integer videoCount = topicDao.selectSumVideoCount(map);
                            resultTopic.put("id",id);
                            resultTopic.put("headPortraitUrl",headPortraitUrl);
                            resultTopic.put("name",topic.getName());
                            resultTopic.put("videoCount",videoCount);
                            topicList.add(resultTopic);
                        }
                    }
                }catch (Exception e){
                    LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
                }
            }
        }else if(searchType.equals(CodeTypeConstant.SEARCH_SEARCH_TYPE_141)){   // 视频
            List<Moment> moments = new ArrayList<>();
            try{
                // 查询视频
                /**
                 *  ES用content_text和content_text.standard查询
                 *  高亮统一用content_text.standard显示, 因为content_text能查询出的content_text.standard也一定能查询出
                 *  设置content_text权重*5
                 *  只查公开
                 */
                MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(content,ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT,ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD).field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT,5f);
                MatchQueryBuilder permissionQuery = QueryBuilders.matchQuery("permission_type", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);// 只查公开的
                BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(queryBuilder).must(permissionQuery);
                highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD);
                SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_MOMENT).setQuery(boolQuery)
                        .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                        .execute().actionGet();
                SearchHits hits = response.getHits();
                for(SearchHit hit : hits){
                    Integer id = (Integer) hit.getSourceAsMap().get("id");   // momentId
                    Moment moment = momentCacheDao.selectByPrimaryKey(id);
                    if(moment != null){
                        // 将搜索的内容替换成高亮搜索结果
                        String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_MOMENT_STANDARD).fragments()[0].toString();
                        moment.setContentText(highLightContent);
                        moments.add(moment);
                    }
                }
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
            }
            // 获取动态结果信息
            for(Moment moment:moments){
                Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);
                String nickName = "";
                String provinceName = "";
                String cityName = "";
                String tempHeadPortraitUrl = "";
                Integer isFollow = 0;
                if(userId > 0){     // 用户有登陆, 查询关注关系
                    if(userId.equals(moment.getPermissionType())){  // 是自己发布的
                        isFollow = -1;  // 自己发布的,没有+ √
                    }else {
                        // 查询是否关注
                        Map<String, Object> tempMap = new HashMap<>();
                        tempMap.put("userId",moment.getPublisher());
                        tempMap.put("followerId",userId);
                        List<UserFollow> userFollows = userFollowDao.selectHasFollow(tempMap);
                        if(userFollows.size() > 0){ // 有关注关系
                            isFollow = 1;
                        }
                    }
                }
                if(moment != null && moment.getPublisher() != null){
                    User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
                    if(user.getResidenceProvince() != null){    // 获取省市名称
                        provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
                    }
                    if(user.getResidenceCity() != null){
                        cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
                    }
                    if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                        tempHeadPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                    }
                    nickName = user.getNickName();
                }
                /* 发布人信息 */
                resultMoment.put("publisher",moment.getPublisher());
                resultMoment.put("nickName",nickName);
                resultMoment.put("provinceName",provinceName);
                resultMoment.put("cityName",cityName);
                resultMoment.put("headPortraitUrl",tempHeadPortraitUrl);
                resultMoment.put("isFollow",isFollow);
                momentList.add(resultMoment);
            }
        }else if(searchType.equals(CodeTypeConstant.SEARCH_SEARCH_TYPE_142)){   // 用户
            // 搜索用户
            try{
                MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER, content);
                highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER);
                SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_USER).setQuery(queryBuilder)
                        .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                        .execute().actionGet();
                SearchHits hits = response.getHits();
                for(SearchHit hit : hits){
                    Integer id = (Integer) hit.getSourceAsMap().get("id");   // 用户id
                    Map<String, Object> resultUser = new HashMap<>();
                    User user = userCacheDao.selectByPrimaryKey(id);
                    if(user != null){
                        // 设置高亮显示
                        String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_USER).fragments()[0].toString();
                        user.setNickName(highLightContent);
                        String headPortraitUrl = "";
                        if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像
                            headPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                        }
                        Integer followCount = userFollowDao.selectFollowerCount(user.getId());    // 粉丝数
                        Integer isFollow = 0;   // 这个默认关注
                        if(userId > 0){     // 用户有登陆, 查询关注关系
                            // 查询是否关注
                            Map<String, Object> map = new HashMap<>();
                            map.put("userId",user.getId());
                            map.put("followerId",userId);
                            List<UserFollow> userFollows = userFollowDao.selectHasFollow(map);
                            if(userFollows.size() > 0){ // 有关注关系
                                isFollow = 1;
                            }
                        }
                        resultUser.put("id",id);
                        resultUser.put("headPortraitUrl",headPortraitUrl);
                        resultUser.put("nickName",user.getNickName());
                        resultUser.put("followCount",followCount);
                        resultUser.put("isFollow",isFollow);
                        userList.add(resultUser);
                    }
                }
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
            }
        }else if(searchType.equals(CodeTypeConstant.SEARCH_SEARCH_TYPE_143)){   // 话题
            // 查询话题
            try{
                MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC, content);
                highlightBuilder.field(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC);
                SearchResponse response = transportClient.prepareSearch(ConfigConstant.ELASTIC_SEARCH_INDEX_NAME_TOPIC).setQuery(queryBuilder)
                        .setFrom(start).setSize(rows).highlighter(highlightBuilder).setExplain(true)
                        .execute().actionGet();
                SearchHits hits = response.getHits();
                for(SearchHit hit : hits) {
                    Integer id = (Integer) hit.getSourceAsMap().get("id");   // 用户id
                    Map<String, Object> resultTopic = new HashMap<>();
                    Topic topic = topicDao.selectByPrimaryKey(id);
                    if(topic != null){
                        // 设置高亮显示
                        String highLightContent = hit.getHighlightFields().get(ConfigConstant.ELASTIC_SEARCH_SEARCH_FIELD_TOPIC).fragments()[0].toString();
                        topic.setName(highLightContent);

                        String headPortraitUrl = "";
                        if(StringUtils.isNotBlank(topic.getHeadPortraitId())){   // 获取头像
                            headPortraitUrl = aliTool.getAccessURL(topic.getHeadPortraitId());
                        }
                        // 查询话题下的视频总数
                        Map<String, Object> map = new HashMap<>();
                        map.put("topicId",id);
                        map.put("remindType", CodeTypeConstant.MOMENT_REMIND_TYPE_100);
                        map.put("permissionType", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);
                        Integer videoCount = topicDao.selectSumVideoCount(map);
                        resultTopic.put("id",id);
                        resultTopic.put("headPortraitUrl",headPortraitUrl);
                        resultTopic.put("name",topic.getName());
                        resultTopic.put("videoCount",videoCount);
                        topicList.add(resultTopic);
                    }
                }
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>>>>搜索动态出错 请求参数:{},错误信息:{}",params,e);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("momentList",momentList);
        result.put("userList",userList);
        result.put("topicList",topicList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 获取热门话题列表
     * @param params
     * @return
     */
    @Override
    public String listHotTopic(Map<String, String> params) {
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));

        Map<String, Object> map = new HashMap<>();
        map.put("start",start);
        map.put("rows",rows);
        /**
         * 获取热门话题列表
         * 最多10个, 数量有后台控制, 业务支持分页
         * 按照searchIndex排序, 数字越小越靠前 0最前
         */
        List<Map<String,Object>> topicList = new ArrayList<>();
        List<Topic> topics = topicDao.selectHotTopicList(map);
        for(Topic topic:topics){
            Map<String, Object> resultTopic = new HashMap<>();
            resultTopic.put("id",topic.getId());
            resultTopic.put("name",topic.getName());
            // 获取该话题下的播放数量
            map.clear();
            map.put("topicId",topic.getId());
            map.put("remindType", CodeTypeConstant.MOMENT_REMIND_TYPE_100);
            map.put("permissionType", CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);
            Integer videoCount = topicDao.selectSumVideoCount(map);
            resultTopic.put("videoCount",videoCount);
            topicList.add(resultTopic);

        }
        Map<String, Object> result = new HashMap<>();
        result.put("topicList",topicList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 热门话题和热搜词
     * @param params
     * @return
     */
    @Override
    public String hotTopicAndHotWord(Map<String, String> params) {

        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);

        List<Map<String,Object>> topicList = new ArrayList<>();
        List<Map<String,Object>> hotTopicList = new ArrayList<>();
        List<Map<String,Object>> hotWordList = new ArrayList<>();
        // 查询热推话题, 在banner处显示 只查6条
        List<Topic> topics = topicDao.selectHotTopicForBanner();
        for (Topic topic : topics){
            Map<String, Object> resultTopic = new HashMap<>();
            resultTopic.put("name",topic.getName());
            resultTopic.put("id",topic.getId());
            String bannerPicUrl = "";
            if(StringUtils.isNotBlank(topic.getBannerPicId())){ // 热推话题banner图
                bannerPicUrl = aliTool.getAccessURL(topic.getBannerPicId());
            }
            resultTopic.put("bannerPicUrl",bannerPicUrl);
            topicList.add(resultTopic);
        }

        // 目前热门话题词最多只有10个,所以这里暂时写死
        Map<String, Object> map = new HashMap<>();
        map.put("start",0);
        map.put("rows",10);
        /**
         * 获取热门话题列表
         * 最多10个, 数量有后台控制, 业务支持分页
         * 按照searchIndex排序, 数字越小越靠前 0最前
         */
        List<Topic> hotTopics = topicDao.selectHotTopicList(map);
        for(Topic topic:hotTopics){
            Map<String, Object> resultTopic = new HashMap<>();
            resultTopic.put("id",topic.getId());
            resultTopic.put("name",topic.getName());
            hotTopicList.add(resultTopic);
        }

        /**
         * 获取热搜词
         */
        List<HotWord> hotWords = hotWordDao.selectHotWordListForApp();
        for(HotWord hotWord : hotWords){
            Map<String, Object> resultTopic = new HashMap<>();
            resultTopic.put("id",hotWord.getId());
            resultTopic.put("name",hotWord.getName());
            hotWordList.add(resultTopic);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("topicList",topicList);
        result.put("hotTopicList",hotTopicList);
        result.put("hotWordList",hotWordList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }


    /**
     * 获取动态视频信息
     * @param realUserId
     * @param refreshWriteTime
     * @param moment
     * @return
     */
    private Map<String, Object> getMomentVideoInfoMap(Integer realUserId, Integer refreshWriteTime, Moment moment) {
        Map<String, Object> resultMoment = new HashMap<>();
        Integer likeCount = 0;
        Integer viewCount = 0;
        Integer shareCount = 0;
        Integer commentCount = 0;
        try{
            // 从redis中获取视频统计信息
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "");
            if(StringUtils.isBlank(momentJson)){    // redis中没有该动态信息, 存入
                MomentCount momentCount = momentCountDao.selectByMomentId(moment.getId());
                if(momentCount == null){
                    MomentCount tempMomentCount = new MomentCount();
                    tempMomentCount.setCountComment(0);
                    tempMomentCount.setCountLike(0);
                    tempMomentCount.setCountShare(0);
                    tempMomentCount.setCountView(0);
                    tempMomentCount.setMomentId(moment.getId());
                    tempMomentCount.setPublisher(moment.getPublisher());
                    tempMomentCount.setCreateTime(new Date());
                    momentCountDao.insertSelective(tempMomentCount);
                    momentCount = tempMomentCount;
                }
                // 存入redis
                Map<String, String> redisMomentMap = new HashMap<>();
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_MOMENT,momentCount.getMomentId()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE,momentCount.getCountLike()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW,momentCount.getCountView()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE,momentCount.getCountShare()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT,momentCount.getCountComment()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW,momentCount.getCountLike()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW_NOW,momentCount.getCountView()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW,momentCount.getCountShare()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW,momentCount.getCountComment()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME,new Date().getTime()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG,1+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "", JSON.toJSONString(redisMomentMap));
            }else {
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                likeCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW));
                viewCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW_NOW));
                shareCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW));
                commentCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW));

                Integer likeCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE));
                Integer viewCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW));
                Integer shareCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE));
                Integer commentCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT));
                Integer isFinish = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG));
                Long writeTime = Long.parseLong(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME));
                long nowTime = new Date().getTime();    // 超过刷新时间才执行
                if(isFinish.intValue() == 1 && ((nowTime - writeTime.longValue()) >= refreshWriteTime)){   // 0:队列存在,等待执行 1:可以发送新的队列
                    if(!likeCount.equals(likeCountOld) || !viewCount.equals(viewCountOld)
                            || !shareCount.equals(shareCountOld) || !commentCount.equals(commentCountOld)){
                        // 数据发生变化,发送队列消息,将新数据写入数据库
                        // 先修改状态位
                        redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG,0+"");  // 处理中
                        stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "", JSON.toJSONString(redisMomentMap));

                        // 修改写入时间
                        redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME,new Date().getTime()+"");
                        amqpTemplate.convertAndSend(ConfigConstant.MESSAGE_NAME_MOMENT_REFRESH_WRITE,redisMomentMap);
                        LOGGER.info(">>>>>>>>>>>>MomentRefreshWriteMessage发出消息, 参数:{}",redisMomentMap.toString());
                    }

                }
            }
        }catch (Exception e){
            LOGGER.error(">>>>>>>>>>>>>>从redis中获取视频信息发生错误, momentId {},错误信息  {}",moment.getId(),e);
        }
        String playUrl = "";
        String coverUrl = "";
        String duration = "0";
        try{
            // 获取视频信息
            Integer videoId = moment.getVideoId();
            Video video = videoCacheDao.selectByPrimaryKey(videoId);
            if(video != null){
                String videoInfo = video.getVideoInfo();
                if(video.getStatus().intValue() == 1 && StringUtils.isNotBlank(videoInfo)){  // 有视频信息缓存
                    VideoInfoBean videoInfoBean = JSON.parseObject(videoInfo, VideoInfoBean.class);
                    playUrl = videoInfoBean.getPlayUrl();
                    coverUrl = videoInfoBean.getCoverUrl();
                    duration = videoInfoBean.getDuration();
                }
            }
        }catch (Exception e){
            LOGGER.error(">>>>>>>>>>>>>>发生错误:获取视频信息  {}",e);
        }
        // 查询该用户是否对视频点赞过
        Integer hasLiked = 0;
        if(realUserId.intValue() > 0){  // 用户未登录时id为-1
            Map<String, Object> tempMap = new HashMap<>();
            tempMap.put("userId",realUserId);
            tempMap.put("momentId",moment.getId());
            List<MomentLike> momentLikeList = momentLikeDao.selectMomentHasLiked(tempMap);
            if(momentLikeList.size() > 0){   // 点过赞
                hasLiked = 1;
            }
        }
        /* 动态社交信息 */
        resultMoment.put("viewCount",viewCount);
        resultMoment.put("likeCount",likeCount);
        resultMoment.put("shareCount",shareCount);
        resultMoment.put("commentCount",commentCount);
        resultMoment.put("hasLiked",hasLiked);
        /* 动态视频信息 */
        resultMoment.put("playUrl",playUrl);
        resultMoment.put("coverUrl",coverUrl);
        resultMoment.put("duration",duration);
        /* 动态信息 */
        resultMoment.put("momentId",moment.getId());
        resultMoment.put("contentText",moment.getContentText());
        resultMoment.put("textExtra",moment.getTextExtra());
        resultMoment.put("permissionType",moment.getPermissionType());
        return resultMoment;
    }
}
